package com.example.flow

import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking
import org.junit.Test


/**
 * 流压缩/组合测试
 * 展平流：
 * 将二维的流转换为一维流
 * 1）flatMapConcat 连接模式
 * 2）flatMapMerge 合并模式
 * 3）flatMapLasted 最新展平模式
 *
 * @author zhouronghua
 * @time 2022/1/7 1:02 下午
 */
class FlowZipTest {

    /**
     * ZIP将两个流合并，流长度取最小值
     *
     * @author zhouronghua
     * @time 2022/1/7 1:03 下午
     */
    @Test
    fun test_flow_zip() = runBlocking {
        println("测试Flow zip")
        val firstFlow = (1..5).asFlow()
        val secondFlow = flowOf("First", "Second", "Third")
        val startTime = System.currentTimeMillis()
        // 第一个流5个元素，第二个流3个元素，组合以后只有3个元素
        firstFlow.zip(secondFlow) { a, b ->
            "$a -> $b"
        }.collect {
            println("收集到组合流 $it at ${System.currentTimeMillis() - startTime} ms")
        }
    }

    fun requestFlow(i: Int) = flow<String> {
        emit("$i First")
        delay(500)
        emit("$i Second")
    }

    /**
     * 展平流连接模式
     *
     * Collect element 1 First
     * Collect element 1 Second
     * 开始进行流展平处理 2
     * Collect element 2 First
     * Collect element 2 Second
     * @author zhouronghua
     * @time 2022/1/7 7:42 下午
     */
    @Test
    fun test_flow_flatMapConcat() = runBlocking {
        println("测试Flow flatMapConcat")
        (1..5).asFlow()
            .onEach {
                delay(100)
            }.flatMapConcat {
                println("开始进行流展平处理 $it")
                requestFlow(it)
            }.collect {
                println("Collect element ${it.toString()}")
            }
    }

    /**
     * 展平流合并模式
     * 开始进行流展平处理 1
     * 开始进行流展平处理 1
     * Collect element 1 First
     * 开始进行流展平处理 2
     * Collect element 2 First
     * 开始进行流展平处理 3
     * Collect element 3 First
     * Collect element 1 Second
     * Collect element 2 Second
     *
     * @author zhouronghua
     * @time 2022/1/7 7:42 下午
     */
    @Test
    fun test_flow_flatMapMerge() = runBlocking {
        println("测试Flow flatMapConcat")
        (1..3).asFlow()
            .onEach {
                delay(100)
            }.flatMapMerge {
                println("开始进行流展平处理 $it")
                // 变成了二位流Flow<Flow<String>>
                requestFlow(it)
            }.collect {
                println("Collect element ${it.toString()}")
            }
    }

    /**
     * 展平流最新合并模式
     * 说明：中间元素丢弃
     *
     * 开始进行流展平处理 1
     * Collect element 1 First
     * 开始进行流展平处理 2
     * Collect element 2 First
     * 开始进行流展平处理 3
     * Collect element 3 First
     * Collect element 3 Second
     * @author zhouronghua
     * @time 2022/1/7 7:42 下午
     */
    @Test
    fun test_flow_flatMapLatest() = runBlocking {
        println("测试Flow flatMapLatest")
        (1..3).asFlow()
            .onEach {
                delay(100)
            }.flatMapLatest {
                println("开始进行流展平处理 $it")
                // 变成了二位流Flow<Flow<String>>
                requestFlow(it)
            }.collect {
                println("Collect element ${it.toString()}")
            }
    }
}